/**
 *@author luoyujia@baidu.com
 *util for the slide img area.
 */

//~ usage:
//~ var Fuck = function(){

//~ SlideUtil.slide([document.getElementById("Fucker").clientWidth, 10, 0.3, 100, function(target, range, isEnd){
  //~ document.getElementById("Fucker").style.width = target + "px";
//~ }]);

//~ }
//~ //@ sourceURL=hello.js
var SlideUtil = (function() {
    
    var self;
    
    var buf = {
        interval : false
    };
    
    var LC = {
        FLOAT_RANGE : 0.00002
    }
    
    var util = {
        /**
         *get the greatest common divisor with Euclidean Algorithm
         */
        getDivisor : function(a, b) {
            
            if (a < b) {
                var c;
                c = a;
                a = b;
                b = c;
            }
            
            while (b != 0) {
                c = a % b;
                a = b;
                b = c;
            }
            
            return a;
        }
    }
    
    var controller = {
        
        /**
         *function that judges the legitimacy of a group of param,
         *also do some basic data transformations.
         *@return array transformed data if legal, false while data not useable.
         */
        judge : function(arg) {
            
            arg[0] = +arg[0];
            arg[1] = +arg[1];
            arg[2] = +arg[2];
            arg[3] = Math.abs(+arg[3]);
            arg[5] && (arg[5] = +arg[5]);
            
            //set 10(ms) as the floor range.
            arg[3] = Math.ceil(arg[3] / 10) * 10;
            
            //any param is not a number
            if (isNaN(Math.max(arg[0], arg[1], arg[2], arg[3]))) return false;
            
            //~ //the case that when "start" is bigger than "end" while "speed" is bigger than 0 will be treated as illgal, and vice versa.
            //~ //at the same time, speed should not be 0.
            //~ if (arg[2] == 0 || (arg[2] > 0 && arg[0] > arg[1]) || (arg[2] < 0 && arg[0] < arg[1])) return false;
            
            //success
            return arg;
        }
    }
    
    return self = {
        /**
         *@param arrays
         *  arguments[0][0] : start value;
         *  arguments[0][1] : end value;
         *  arguments[0][2] : speed, for example 0.3 for 30% per interval;
         *  arguments[0][3] : interval range, 100(ms) is suit for most cases, 10(ms) is the floor range;
         *  arguments[0][4] : callback function, will be evalued at the end of every interval, reviece param as below:
         *  [arguments[0][4]] : float range, if it's a float slide, the range that defines end tag:
         *@paramForCallback target value;
         *@paramForCallback range value;
         *@paramForCallback isEnd is this interval the last one;
         */
        slide : function() {
            var slides = [],
                endTags = [],
                timer = 0,
                _buf = buf;
            
            var temp;
            //format input data.
            for (var i = 0, len = arguments.length; i < len; ++i) {
                
                temp = controller.judge(arguments[i]);
                
                //skip if illgal
                if (!temp) continue;
                
                slides.push(temp);
                timer = timer || temp[3];
                
                //get the greatest common divisor of all intervals.
                timer = util.getDivisor(timer, temp[3]);
            }
            
            clearInterval(_buf.interval);
            //let's go!
            _buf.interval = setInterval(function(){
                
                var ranges = [],
                    end = false,
                    isInteger = false;
                for (var i = 0, len = slides.length; i < len; ++i) {
                    
                    if (timer % slides[i][3] != 0 || endTags[i]) {
                        end = end || !!endTags[i];
                        continue;
                    }
                    
                    ranges[i] = slides[i][1] - slides[i][0];
                    
                    //end flag judgement
                    if (ranges[i] == 0 ||  Math.abs(ranges[i]) <= slides[i][5] || Math.abs(ranges[i]) <= LC.FLOAT_RANGE) {
                        endTags[i] = 1;
                    
                        //the last callback
                        (slides[i][4] instanceof Function) && slides[i][4](slides[i][1], ranges[i], !!endTags[i]);
                    
                        continue;
                    }
                    
                    //range = (end - start) * speed;
                    //start = start + range;
                    isInteger = slides[i][0] === ~~slides[i][0];
                    slides[i][0] = slides[i][0] + ranges[i] * slides[i][2];
                    isInteger && (slides[i][0] = ranges[i] > 0 ? Math.ceil(slides[i][0]) : Math.floor(slides[i][0]));
                    
                    //callback
                    /**
                     *@param target value
                     *@param range value
                     *@param end tag
                     */
                    (slides[i][4] instanceof Function) && slides[i][4](slides[i][0], ranges[i], !!endTags[i]);
                }
                
                timer += timer;
                end && clearInterval(_buf.interval);
            }, timer);
        },
        
        abort : function() {
            clearInterval(buf.interval);
        }
    }
})();

/**
 *main func for slider in detail.html
 */
(function() {
    
    var LC = {
        MAX_WIDTH : 480
    };
    
    var buf = {
        imgCount : 0,
        imgs : [],
        imgWrap : "",
        currentIndex : 0,
        avalible : true
    };
    
    var view = {
        lastBtn : false,
        nextBtn : false
    };
        
    var controller = {
        
        /**
         *@param direction -1 slide from left to right;
         */
        slide : function(direction) {
            
            var start = 0;
            if (!buf.avalible) return;
            
            direction = +direction;
            if (!direction) return;
            direction = direction % buf.imgCount;
            
            buf.avalible = false;
            
            start = buf.currentIndex * LC.MAX_WIDTH * -1;
            buf.imgWrap.style.marginLeft = start + "px";
            
            SlideUtil.slide([start, (direction - buf.currentIndex) * LC.MAX_WIDTH, 0.36, 30, function(target, range, isEnd) {
                if (!isEnd) {
                    buf.imgWrap.style.marginLeft = target + "px";
                } else {
                    //when it's at the penultimate picture, append the first img to the last position.
                    buf.avalible = true;
                }                
                
                //img buffer
                controller.exchange();
            }]);
            
            buf.currentIndex = (buf.currentIndex - direction) % buf.imgCount;
        },
        
        exchange : function() {
            
            view.lastBtn.style.display = buf.currentIndex == 0 ? "none" : "block";
            view.nextBtn.style.display = buf.currentIndex == (buf.imgs.length - 1) ? "none" : "block";
        },
        
        /**
         *@changes buf.imgs(used by slide), buf.maxHeight(used by onload)
         */
        getImgList : function() {
    
            buf.imgs = [];
            for (var i = 0, len = buf.imgWrap.childNodes.length; i < len; ++i) {
                
                if (buf.imgWrap.childNodes[i].tagName && buf.imgWrap.childNodes[i].tagName.toLowerCase().match(/img/)) {
                    buf.imgs.push(buf.imgWrap.childNodes[i]);
                } else continue;
            }
        }
    }
    
    window.onload = function() {
        
        view.lastBtn = document.getElementById("slideLeftBtn");
        view.nextBtn = document.getElementById("slideRightBtn");
        
        //find image nodes
        buf.imgWrap = document.getElementById("slideImgWrap");
        if (!buf.imgWrap || !view.lastBtn || !view.nextBtn) return;
        
        controller.getImgList();
        controller.exchange();
        
        //record buffer
        buf.imgCount = buf.imgs.length;
        buf.imgWrap.style.width = buf.imgs.length * LC.MAX_WIDTH + "px";
        
        //bind event
        view.lastBtn.onclick = function() {
            controller.slide(1);
        };
        view.nextBtn.onclick = function() {
            controller.slide(-1);
        };
    };
    
})();